/*
 * config.cpp
 *
 *  Created on: 2012-3-21
 *      Author: ncrd
 */
#include <iostream>

#include "config.h"

/*const char *default_frequency = "1";
const char *default_mode = "1";
const char *default_brocast_IP = "0.0.0.0";
const char *Config_file = "/mnt/etc/IEEE1588/Config.xml";*/


using namespace std;

const char *default_frequency = "1";
const char *default_mode = "3";
const char *Config_file = "/mnt/etc/IEEE1588/Config.xml";

//used for xml file
bool xml_flag = false;
xmlDocPtr pDoc = NULL;

/************************************************************************/
/*
open a xml file, if the file does not exist, or the format isn't correct,
then create a new file!
*/
/************************************************************************/
xmlDocPtr OpenXML(const char *filename){
	//read the file first, if failed, a new file with default set will be created.
	xmlDocPtr doc = xmlReadFile(filename,NULL,XML_PARSE_RECOVER);
	if(doc == NULL) {
		#ifdef _debug_
		cout << "				The default configuration file " << filename << " doesn't exist. " << endl;
		cout << "				We'll try to create a new xml file!" << endl;
		#endif
		doc = xmlNewDoc(BAD_CAST"1.0");
		xmlNodePtr root_node = xmlNewNode(NULL,BAD_CAST"Configuration");
		xmlDocSetRootElement(doc,root_node);
		//default frequency and mode
		xmlNewTextChild(root_node,NULL,BAD_CAST"Frequency",BAD_CAST default_frequency);
		xmlNewTextChild(root_node,NULL,BAD_CAST"Mode",BAD_CAST default_mode);


		//发送是单播还是多播，以下代码已弃用
		/*xmlNodePtr cast_mode = xmlNewNode(NULL,BAD_CAST"Castmode");
		xmlAddChild(root_node,cast_mode);
		xmlNewTextChild(cast_mode,NULL,BAD_CAST"number",BAD_CAST "1");
		xmlNewTextChild(cast_mode,NULL,BAD_CAST"IP1",BAD_CAST default_brocast_IP);*/


		int nRet = xmlSaveFile(filename,doc);
		if(nRet == -1) {
			#ifdef _debug_
			cout << "				Create new file " << filename << " failed!" << endl;
			#endif
			return NULL;
		}
		#ifdef _debug_
		cout << "				A new configuration file " << filename << " is created successfully!" << endl;
		#endif
	}
	return doc;
}

/**
 * 通过config(XML中的标签)获取与该标签相对应的值
 */
string get_config(string config){
	string ret_str;
	xmlDocPtr doc = xmlReadFile(Config_file,NULL,XML_PARSE_RECOVER);
	if(doc == NULL)
		cout << "Can not get the information of frequency and cast mode" << endl;
	else {
		xmlNodePtr curNode = xmlDocGetRootElement(doc),tmpNode;

		//make sure the file isn't empty
		if(curNode == NULL) {
			cout << "File format error: the configuration file is empty" << endl;
			xmlFreeDoc(doc);
			return NULL;
		}

		//check if the root's name is Configuration
		if(xmlStrcmp(curNode->name,BAD_CAST"Configuration")) {
			cout << "File format error: the root's name is error" << endl;
			xmlFreeDoc(doc);
			return NULL;
		}

		// find the node called $config
		// 使用BAD_CAST将string转换转换成xmlChar *
		tmpNode = curNode = curNode->children;
		while(curNode != NULL) {
			if(!xmlStrcmp(curNode->name,BAD_CAST config.c_str())) {
				xmlChar *s = xmlNodeGetContent(curNode);
				ret_str.assign((char *)s); //利用xmlChar *给string赋值，不能直接用操作符=
				xmlFree(s);
				break;
			}
			curNode = curNode->next;
		}
	}
	xmlFreeDoc(doc);	//退出函数前必须释放doc，否则占用内存空间
	return ret_str;
}

/**
 * 设置config.xml文件中的值
 */
int set_config(string config,string value){
	/*check the format of the mode*/
	//add the code for checking format here
	if(pDoc == NULL)
		pDoc = OpenXML(Config_file);
	if(pDoc == NULL) {
		#ifdef _debug_
		cout << "				Open XML file " << Config_file << " failed" << endl;
		#endif
		return -1;
	}

	xmlNodePtr curNode = xmlDocGetRootElement(pDoc);

	//make sure the file isn't empty
	if(curNode == NULL) {
		#ifdef _debug_
		cout << "				File format error: the configuration file is empty" << endl;
		#endif
		xmlFreeDoc(pDoc);
		pDoc = NULL;
		return -1;
	}

	//check if the root's name is Configuration
	if(xmlStrcmp(curNode->name,BAD_CAST"Configuration")) {
		#ifdef _debug_
		cout << "				File format error: the root's name is error" << endl;
		#endif
		xmlFreeDoc(pDoc);
		pDoc = NULL;
		return -1;
	}

	//find the node called "Mode"
	curNode = curNode->children;
	while(curNode != NULL) {
		if(!xmlStrcmp(curNode->name,BAD_CAST(config.c_str()))) {
			xmlNodeSetContent(curNode,BAD_CAST(value.c_str()));
			break;
		}
		curNode = curNode->next;
	}
	if(curNode == NULL) {
		#ifdef _debug_
		cout << "				Can't find the node Mode" << endl;
		#endif
		xmlFreeDoc(pDoc);
		pDoc = NULL;
		return -1;
	}
	xml_flag = true;
	return 0;
}

/**
 * 恢复Config.xml到默认配置
 */
int reset_config(void) {
	xmlDocPtr doc = xmlNewDoc(BAD_CAST"1.0");
	xmlNodePtr root_node = xmlNewNode(NULL,BAD_CAST"Configuration");
	xmlDocSetRootElement(doc,root_node);
	xmlNewTextChild(root_node,NULL,BAD_CAST"Frequency",BAD_CAST default_frequency);
	xmlNewTextChild(root_node,NULL,BAD_CAST"Mode",BAD_CAST default_mode);

	if(xmlSaveFile(Config_file,doc) == -1) {
		#ifdef _debug_
		cout << "				Save xml file failed!" << endl;
		#endif
		return -1;
	}
	xmlFreeDoc(doc);
	xml_flag = false;
	cout << "				Reset the frequency and mode successfully!" << endl << endl;
	return 0;
}

int save_config(void) {
	//check if there are changes about the xml file
	if(xml_flag) {
		if(xmlSaveFile(Config_file,pDoc) < 0) {
			#ifdef _debug_
			cout << "				save xml file " << Config_file << " failed!"<< endl;
			#endif
			return -1;
		}
		xmlFreeDoc(pDoc);
		pDoc = NULL;
		xml_flag = false;
	}
	cout << "				Save frequency and mode settings successfully!" << endl << endl;
	return 0;
}

int abort_save_config(void) {
	if(pDoc)
		xmlFreeDoc(pDoc);
	pDoc = NULL;
	xml_flag = false;
	return 0;
}
